home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part2 / 14317 < prev    next >
Encoding:
Text File  |  1996-08-05  |  7.7 KB  |  154 lines

  1. Newsgroups: comp.lang.c++
  2. Path: nntp.coast.net!torn!sq!news
  3. From: willer@carolian.com (Steve Willer)
  4. Subject: Re: Microsoft Visual C++ vs. Borland C++
  5. Message-ID: <315c2fff.72171602@sqarc.sq.com>
  6. Sender: news@sq.com (News Administrator)
  7. Organization: Carolian Systems, Toronto ON
  8. X-Newsreader: Forte Agent .99d/32.182
  9. References: <4iria4$i76@granite.sentex.net> <4is07r$9cc@news1.h1.usa.pipeline.com> <4jacau$ibg@comet.magicnet.net>
  10. Date: Fri, 29 Mar 1996 21:26:36 GMT
  11.  
  12. catello@magicnet.net (Michael Catello) wrote:
  13.  
  14. >What makes OWL more object-oriented? I haven't used Borland's products
  15. >in a couple of years but have been real happy with MSVC. (Borland
  16. >really pissed me off once; I had been using BC++ for a while, and they
  17. >had a big push for their ObjectVision product which they marketed to
  18. >developers. I purchased it when a Borland Salesperson called me and a
  19. >month later they dropped the product. This was enuf to completely turn
  20. >me off on the company).
  21.  
  22. Well, certainly, Borland has made some PR mistakes in the past, and
  23. it's annoyed quite a lot of customers. However, they do have a new
  24. policy of actually reporting bugs, which I hope is part of a new
  25. direction in their customer service.
  26.  
  27. As for OWL vs. MFC, I find that it is quite a bit more OO than MFC in
  28. the sense that it is far more polymorphic and abstract. OWL makes use
  29. of multiple-inheritance in appropriate classes, its container classes
  30. don't depend on a Smalltalk-style. MFC functions tend to be nothing
  31. more than wrappers around WIN SDK functions, with the same naming and
  32. parameters, which I never liked because not only is the SDK not C++,
  33. it's poorly designed at that.
  34.  
  35. We don't have MSVC4 here, but I do have some legacy code that uses MFC
  36. 2, compiled with BC++. An example of the kinds of differences I'm
  37. talking about are TDC vs. CDC.  TDC is written as a true
  38. resource-cleaning class, in that when you create it, it remembers the
  39. handles of the stock objects it started with. So, if you call
  40. something like myDC.SelectObject(myBrush), it will automatically clean
  41. up. Plus, SelectObject is overridden for each TBitmap, TBrush, etc.,
  42. and it takes a reference to the object rather than a pointer.
  43.  
  44. Anyway, here's some simple code, grabbed from my legacy app, written
  45. in MFC2:
  46.  
  47.    // Dc is a "CDC*" parameter
  48.    CDC dcMem;
  49.    Dc->CreateCompatibleDC(&dcMem);
  50.    CBrush *fillbrush,*oldbrush;
  51.    fillbrush = new CBrush(GetSysColor(COLOR_BTNFACE));
  52.    oldbrush = dcMem.SelectObject(fillbrush);
  53.    // do some drawing
  54.    dcMem.SelectObject(oldbrush);
  55.    delete fillbrush;
  56.  
  57. There are many things that are done here that are completely
  58. unnecessary and in fact are dangerous. For one, I don't understand why
  59. it takes pointers instead of references, since NULL parameters are not
  60. legal here. But that's a minor issue.
  61.  
  62. The bigger issue here is that, just like the Win API, the programmer
  63. is required to select the original brush back into the DC before
  64. destroying the DC. There is no reason for MFC to require this, as
  65. evidenced by the fact that OWL doesn't. Plus, why do CDC::Delete() and
  66. CGDIObject:DeleteObject() even exist as public functions? This only
  67. serves to further blur the encapsulation of GDI objects. Does a CBrush
  68. instance represent a "Windows brush"? Does it represent zero? That's
  69. not clear. And what about that CreateCompatibleDC function? I'm
  70. obviously not creating a new CDC, because I'm giving it one that it's
  71. modifying. So what am I creating? Well, it turns out I am creating a
  72. new "Windows DC", but not a new CDC. This, again, blurs the
  73. encapsulation of the GDI object, making the code further confused.
  74. Plus, the SelectObject() function returns a _pointer_ to a brand-new
  75. TBrush! It is not at all clear by the semantics of the function
  76. whether the client code should delete this object!
  77.  
  78. It seems to me to be much clearer to have a CBrush represent a single
  79. Windows brush, and to have a single CDC represent a single DC. Plus,
  80. the DC should be able to completely clean up after itself -- that's
  81. why God gave us constructors and destructors. And why the
  82. CreateCompatibleDC? Why not use a single-argument constructor? And, of
  83. course, why does CreateCompatibleDC() take a pointer to DC when it
  84. doesn't allow a NULL value?
  85.  
  86. Anyway, here's equivalent code in OWL.
  87.  
  88.    // rDC is a "TDC&" parameter
  89.    TMemDC MemDC(rDC);
  90.    CBrush FillBrush(::GetSysColor(COLOR_BTNFACE));
  91.    MemDC.SelectObject(FillBrush);
  92.    // do some stuff
  93.  
  94. That's it! Not only is the code shorter, it's more concise. Plus, it
  95. comes closer to the ideal of "self-documenting code" because more of
  96. the code is directly related to the purpose of the function (drawing
  97. some stuff) and none of it is related to cleaning up. Plus, there are
  98. no opportunities for the developer to forget to clean something up.
  99.  
  100. And guess what the other great thing about this is? It's _exception
  101. safe_! Because OWL uses self-contained classes that clean up after
  102. themselves, I don't need to worry about a thrown exception causing my
  103. program to leak resources.
  104.  
  105. >>I guess you mean onus.  I think that learning the langugage *is* 
  106. >>the reponsibility of the individual.  Microsoft may make the 
  107. >>development of Windows applications easier, but for learning 
  108. >>the language, this "easiness" can actually be detrimental.  It's 
  109. >>easy for me to picture someone with a year or more development 
  110. >>experience with MSVC++ but having only a shallow knowledge of 
  111. >>the C++ language itself. 
  112. >
  113. >I get the impression that you think that making development easier is
  114. >a bad thing. There will always be bad programmers who never experiment
  115. >with the language and try to extend their experiences and learning,
  116. >but who are just out to get the job done (much to the chagrin of those
  117. >of us that have to go in after as cleanup). These people can never be
  118. >saved or helped by even the most pure of environments. But for the
  119. >rest of us, making development easier for the redundant tasks that
  120. >were all too common in old Win SDK days is like manna from heaven.
  121.  
  122. I don't think that's what the original poster is referring to. I've
  123. found that one of the easiest ways to make a project late and of poor
  124. quality is to forget the long-term and go for the instant
  125. gratification. I recently read through a book on development
  126. management written by the Visual C++ product manager, and I was
  127. appalled at his attitude about C++ (although the book itself was
  128. well-written and informative, and I would recommend it -- I just don't
  129. recommend the compiler). His claim was that giving up-to-date C++
  130. support wasn't worth it because most people weren't actually
  131. programming in C++ at the time. So they chose to create their
  132. AppWizards and stuff, which is a great idea, but they completely
  133. forgot about the part that comes after using AppWizard -- the
  134. developer-written code.
  135.  
  136. This is a typical short-term view on things that I strongly disagree
  137. with. When a developer writes code, when someone designs a program,
  138. when tests are designed for the product, it is absolutely vital to
  139. consider the long-term viability and maintainability of the product.
  140. This not only helps maintenance of the product in the future -- it
  141. promotes clean code that will have less bugs during development, and
  142. the remaining bugs will be easier to fix. Microsoft's attitude, which
  143. seems to be to push the "bleeding-edge" Windows APIs while dismissing
  144. the practical value of C++ features like templates, exceptions,
  145. polymorphism and exceptions, is in my view a sure-fire recipe for bugs
  146. that could have been avoided with a cleaner library design.
  147.  
  148. Of course, Microsoft's doing pretty well with their compiler, and as
  149. long as I can still use BC++, I'm happy for them. But I'm not going to
  150. make a decision on a compiler for myself based on what's best for
  151. Microsoft. I have to think of myself and my colleagues and what's best
  152. for us. Of course, what's best for us is code that we won't have to
  153. worry too much about.
  154.